#include <thread>
#include "Node.h"
#include "DataFrame.h"
#include <unistd.h>
#include <iostream>
RemoteMaster remoteMaster;
void RemoteMaster::printInfo() {
    char ip[16];
    this->si.getip(ip);
    std::cout << "status :\t" << (this->connected ? "established" : "disconnected") << std::endl;
    std::cout << "IP :" << ip << " port :\t" << ntohs(this->si.addr.sin_port) << std::endl;
}
void RemoteMaster::setSocket(socketinf si) {
    if (this->connected) {
        si.close();
        throw SocketException("Connect has establish");
    }
    this->mutex.lock();
    this->doki = 0;
    this->si = si;
    this->connected = true;
    this->mutex.unlock();
}

void RemoteMaster::sendDoki() {
    DataFrame df;
    try {
        while (1) {
            df.sendFrame(this->si.socket_fd, PC::CtrlFrameFlag::doki, 0);
            if(this->doki++ > 3) {
                throw TimeoutException();
            }
            sleep(3);
        }
    } catch(const Exception& e){
        try {
            this->closeConnect();
        } catch(...) {}
        std::cout << "Master connection closed" << std::endl;
        std::cerr << e.what() << '\n';
    }
    
}

void RemoteMaster::closeConnect() {
    if (!this->connected) {
        return;
        // throw SocketException("Connect has not establish");
    }
    this->mutex.lock();
    this->doki = 0;
    this->connected = false;
    this->si.close();
    this->mutex.unlock();

}

void RemoteMaster::acceptControl() {
    if (!this->connected) {
        return;
        // throw SocketException("Connect has not establish");
    }
    DataFrame df;
    char buf[8192];
    try {
        while (df.readFrame(this->si.socket_fd)) {
            switch (df.flag) {
                case PC::CtrlFrameFlag::doki : this->doki = 0; /* std::cout << "Recive doki from master"  << std::endl */; break;
                case PC::CtrlFrameFlag::sendmsg :
                    recv(this->si.socket_fd, buf, df.length, MSG_WAITALL);
                    std::cout << "[master message]" << buf << std::endl;
                    break;
                default: std::cout << "unknow flag:" << (int)df.flag << std::endl; break;
            }
        }
    } catch(...) {
        std::cout << "Master connection close" << std::endl;
        this->closeConnect();
    }
}
